#include "NetworkTransmitter.hpp"
#include "camera_type.h"
#include "cbb_log_api.h"
#include "cbb_socket_api.h"
#include <iostream>

NetworkTransmitter::NetworkTransmitter(int cameraId)
    : m_cameraId(cameraId), m_socketFd(-1), m_running(false), m_sendQueue(20) {} // 队列大小设为100，可以根据需要调整

NetworkTransmitter::~NetworkTransmitter() {
    stop();
    closeSocket();
}

bool NetworkTransmitter::initialize(const TransportConfig &config) {
    m_config = config;
    return connectToServer();
}

bool NetworkTransmitter::connectToServer() {
    closeSocket();

    if (m_config.protocol == UDP) {
        m_socketFd = CBBConnectUDPSocketServer(CBBSocketTypeEnum_t::CBB_SOCKET_IP_NAME,
                                               (hd_s8_t *)m_config.address.c_str(),
                                               m_config.port, nullptr);
    } else if (m_config.protocol == LOCAL_SOCKET) {
        m_socketFd = CBBConnectLocalSocket((hd_s8_t *)m_config.address.c_str());
    }

    if (m_socketFd < 0) {
        std::cerr << "Failed to connect socket for camera " << m_cameraId << std::endl;
        return false;
    }else {
        std::cout << "connect success addr: " << m_config.address << " port: " << m_config.port << std::endl;
    }

    return true;
}

void NetworkTransmitter::closeSocket() {
    if (m_socketFd >= 0) {
        CBBCloseSocket(m_socketFd);
        m_socketFd = -1;
    }
}

int NetworkTransmitter::sendData(const NetworkFrameData &frameData) {
    if (!m_sendQueue.push(frameData)) {
        std::cerr << "Send queue is full for camera " << m_cameraId << std::endl;
        return -1;
    }
    return 0;
}

void NetworkTransmitter::updateConfig(const TransportConfig &config) {
    if (m_config.protocol != config.protocol ||
        m_config.address != config.address ||
        m_config.port != config.port) {
        m_config = config;
        connectToServer();
    }
}

void NetworkTransmitter::start() {
    if (!m_running) {
        m_running = true;
        m_sendThread = std::thread(&NetworkTransmitter::sendLoop, this);
    }
}

void NetworkTransmitter::stop() {
    if (m_running) {
        m_running = false;
        if (m_sendThread.joinable()) {
            m_sendThread.join();
        }
    }
}

void NetworkTransmitter::sendLoop() {
    while (m_running) {
        std::cout << "into send loop" << std::endl;
        NetworkFrameData frameData;
        if (m_sendQueue.wait_for(frameData, 100) == 0) { // 等待100ms
            if (m_socketFd >= 0) {
                if (m_config.protocol == CAMERA_TARN_PRO_UDP) {
                    std::cout << "into udp" << std::endl;
                    sendUDP(frameData);
                } else {
                    sendLocalSocket(frameData);
                }
            }else {
          std::cout << "socket fd invalid" << std::endl;
            }
        }else {
          std::cout << "queue timeout" << std::endl;
        }
    }
}

void NetworkTransmitter::sendUDP(const NetworkFrameData &frameData) {
    int result = CBBWriteSocket(m_socketFd,
                                const_cast<void *>(static_cast<const void *>(frameData.data.data())),
                                frameData.data.size(),
                                1000);
    if (result < 0) {
        CbbLogError("Failed to send UDP packet for camera %d: %d", m_cameraId, result);
        connectToServer(); // 尝试重新连接
    } else {
        CbbLogInfo("Successfully sent UDP packet for camera %d: %d bytes", m_cameraId, result);
        std::cout << "Successfully sent UDP packet for camera " << m_cameraId << ": " << result << " bytes" << std::endl;
    }
#if 0
    hd_u32_t totalPackets = (frameData.data.size() + 1299) / 1300; // 向上取整

    for (hd_u32_t i = 0; i < totalPackets; ++i) {
        CameraTranPacket_t packet;
        packet.total = totalPackets;
        packet.cnt = i + 1;
        packet.timestamp = frameData.unixTimestamp;

        hd_u16_t dataLen = (i == totalPackets - 1) ? (frameData.data.size() % 1300) : 1300;
        if (dataLen == 0)
            dataLen = 1300; // 处理整除的情况

        packet.data_len = dataLen;
        memcpy(packet.data, frameData.data.data() + i * 1300, dataLen);

        int result = CBBWriteSocket(m_socketFd, &packet, sizeof(CameraTranPacket_t), 1000);
        if (result < 0) {
            CbbLogError("Failed to send UDP packet %d/%d for camera %d: %d",
                        i + 1, totalPackets, m_cameraId, result);
            connectToServer(); // 尝试重新连接
            break;             // 跳出当前帧的发送循环
        }
    }
#endif
}

void NetworkTransmitter::sendLocalSocket(const NetworkFrameData &frameData) {
    hd_s32_t result = CBBWriteSocket(
        m_socketFd,
        static_cast<void *>(const_cast<uint8_t *>(frameData.data.data())),
        static_cast<hd_s32_t>(frameData.data.size()),
        static_cast<hd_s64_t>(1000));

    if (result < 0) {
        CbbLogError("Failed to send data for camera %d: %d", m_cameraId, result);
        connectToServer(); // 尝试重新连接
    }
}